package com.ada;

public class Base64 {

    private static final char[] BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray();

    public static String encode(String data) {
        byte[] bytesToEncode = data.getBytes();
        StringBuilder result = new StringBuilder();
        int paddingCount = (3 - (bytesToEncode.length % 3)) % 3;

        byte[] paddedBytes = new byte[bytesToEncode.length + paddingCount];
        System.arraycopy(bytesToEncode, 0, paddedBytes, 0, bytesToEncode.length);

        for (int i = 0; i < paddedBytes.length; i += 3) {
            int j = ((paddedBytes[i] & 0xFF) << 16) | ((paddedBytes[i + 1] & 0xFF) << 8) | (paddedBytes[i + 2] & 0xFF);
            result.append(BASE64_CHARS[(j >> 18) & 0x3F]);
            result.append(BASE64_CHARS[(j >> 12) & 0x3F]);
            result.append(BASE64_CHARS[(j >> 6) & 0x3F]);
            result.append(BASE64_CHARS[j & 0x3F]);
        }

        for (int i = 0; i < paddingCount; i++) {
            result.setCharAt(result.length() - 1 - i, '=');
        }

        return result.toString();
    }
    public static byte[] base64Decode(String str) {
        int length = str.length();
        int paddingCount = 0;
        if (length > 0) {
            if (str.charAt(length - 1) == '=') {
                paddingCount++;
            }
            if (str.charAt(length - 2) == '=') {
                paddingCount++;
            }
        }
        int outLength = length * 6 / 8 - paddingCount;
        byte[] result = new byte[outLength];
        int shift = 0;
        int acc = 0;
        int index = 0;
        for (int i = 0; i < length; i++) {
            int value = charToInt(str.charAt(i));
            if (value >= 0) {
                acc <<= 6;
                shift += 6;
                acc |= value;
                if (shift >= 8) {
                    shift -= 8;
                    result[index++] = (byte) ((acc >> shift) & 0xff);
                }
            }
        }
        return result;
    }

    private static int charToInt(char ch) {
        if (ch >= 'A' && ch <= 'Z') {
            return ch - 'A';
        }
        if (ch >= 'a' && ch <= 'z') {
            return ch - 'a' + 26;
        }
        if (ch >= '0' && ch <= '9') {
            return ch - '0' + 52;
        }
        if (ch == '+') {
            return 62;
        }
        if (ch == '/') {
            return 63;
        }
        return -1;
    }
    public static String decode(String encodedData) {

        return new String(base64Decode(encodedData));
    }
    public static void main(String[] args) {
        String data = "Hello, world!中国";
        String encodedData = Base64.encode(data);
        System.out.println("Encoded data: " + encodedData);
        String decodedData = Base64.decode(encodedData);
        System.out.println("Decoded data: " + decodedData);
    }

}
